package com.jack.xiaoer.web.controller;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.exc.InvalidFormatException;
import com.jack.xiaoer.cache.LocalCache;
import com.jack.xiaoer.constant.LoginTypeEnum;
import com.jack.xiaoer.service.error.AccountExistedException;
import com.jack.xiaoer.service.impl.MailNoifyService;
import com.jack.xiaoer.service.AccountService;
import com.jack.xiaoer.service.error.AccountLockedException;
import com.jack.xiaoer.service.error.ServiceException;
import com.jack.xiaoer.util.AjaxResponse;
import com.jack.xiaoer.dto.AccountDTO;
import com.jack.xiaoer.util.JWTUtil;
import com.jack.xiaoer.validator.Groups;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.MailException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.mail.SendFailedException;
import java.util.List;
import java.util.Optional;

/**
 * Created by Jackaroo Zhang on 2018/12/6.
 */
@Validated
@RestController
@RequestMapping("/account")
public class AccountController extends BaseController {

    private final Logger logger = LoggerFactory.getLogger(AccountController.class);

    private static final String MAIL_VERIFY_PREFIX = "mail_";

    @Autowired
    private AccountService accountService;

    @Autowired
    private MailNoifyService mailNoifyService;

    @PostMapping("/login")
    public AjaxResponse login(@RequestBody @Validated(Groups.Login.class) Optional<AccountDTO> accountDTO
            , BindingResult bindingResult) {
        AjaxResponse validateResult = commonValidate(accountDTO, bindingResult);
        if (validateResult != null) {
            return validateResult;
        }

        AccountDTO account = accountService.getAccount(accountDTO);
        if (account == null) {
            return AjaxResponse.fail("登录失败，不存在该用户");
        }

        String token = JWTUtil.getToken(account);
        return AjaxResponse.success("登录成功", account, token);
    }

    @PostMapping("/register")
    public AjaxResponse register(@RequestBody @Validated(Groups.Register.class) Optional<AccountDTO> accountDTO, BindingResult bindingResult) {
        AjaxResponse validateResult = commonValidate(accountDTO, bindingResult);
        if (validateResult != null) {
            return validateResult;
        }

        String verifyCode = LocalCache.getKey(MAIL_VERIFY_PREFIX + accountDTO.get().getUsername());
        if (StringUtils.isBlank(verifyCode) || !StringUtils.equals(verifyCode, accountDTO.get().getVerifyCode())) {
            return AjaxResponse.invalid("验证码错误");
        }

        AccountDTO account = accountService.createAccount(accountDTO);
        if (account == null) {
            return AjaxResponse.fail("注册失败");
        }

        return AjaxResponse.success("注册成功", account);
    }

    @PostMapping("/send_verify_code")
    public AjaxResponse sendVerifyCode(@RequestBody @Validated(Groups.Email.class) Optional<AccountDTO> accountDTO, BindingResult bindingResult) {
        AjaxResponse validateResult = commonValidate(accountDTO, bindingResult);
        if (validateResult != null) {
            return validateResult;
        }

        if (accountService.accountExisted(accountDTO)) {
            return AjaxResponse.invalid("邮箱已被使用");
        }

        String mailAddress = accountDTO.get().getUsername();
        String value = LocalCache.getKey(MAIL_VERIFY_PREFIX + mailAddress);
        if (StringUtils.isNotBlank(value)) {
            return AjaxResponse.fail("请等待5分钟后，旧验证码过期后重试");
        }

        int verifyCode = RandomUtils.nextInt(100000, 1000000);
        mailNoifyService.sendVerifyCode(verifyCode+"", mailAddress);
        LocalCache.setKey(MAIL_VERIFY_PREFIX + mailAddress, verifyCode+"");

        return AjaxResponse.success("验证码已发送，请登录邮箱查看");
    }

    @PostMapping("/test")
    public AjaxResponse test(Optional<LoginTypeEnum> loginTypeEnum) {

        return AjaxResponse.invalid("msg", loginTypeEnum);
    }


    /**
     * 异常处理，处理因为参数错误而导致的异常
     * @param e
     * @return
     */
    @ExceptionHandler({ InvalidFormatException.class })
    public AjaxResponse handleParameterFormatException(InvalidFormatException e) {
        return AjaxResponse.invalid(e.getMessage());
    }

    @ExceptionHandler({JsonParseException.class})
    public AjaxResponse handleParseParmeterException(JsonParseException e) {
        return AjaxResponse.error("Json解析异常");
    }

    /**
     * 服务层抛出异常的处理
     * @param e
     * @return
     */
    @ExceptionHandler({ ServiceException.class })
    public AjaxResponse handleServiceException(ServiceException e) {
        if (e instanceof AccountLockedException) {
            return AjaxResponse.fail(e.getMessage());
        }
        if (e instanceof AccountExistedException) {
            return AjaxResponse.invalid(e.getMessage());
        }
        if (e.getCause() instanceof MailException) {
            return AjaxResponse.invalid("邮件发送失败");
        }

        return AjaxResponse.fail("service error");
    }


}
